{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5f218873",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from dotenv import load_dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "# Configure an LLM\n",
    "llm = ChatOpenAI(\n",
    "    model=\"qwen3-32b\",\n",
    "    temperature=0.5,\n",
    "    base_url=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "    api_key=os.environ.get(\"AI_DASHSCOPE_API_KEY\"),\n",
    "    streaming=True,\n",
    "    extra_body={\"enable_thinking\": False}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "cd359b39",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Annotated\n",
    "\n",
    "from langchain_tavily import TavilySearch\n",
    "from typing_extensions import TypedDict\n",
    "\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "from langgraph.graph import StateGraph, START\n",
    "from langgraph.graph.message import add_messages\n",
    "from langgraph.prebuilt import ToolNode, tools_condition\n",
    "\n",
    "class State(TypedDict):\n",
    "    messages: Annotated[list, add_messages]\n",
    "\n",
    "graph_builder = StateGraph(State)\n",
    "\n",
    "search_tool = TavilySearch(max_results=2)\n",
    "tools = [search_tool]\n",
    "llm_with_tools = llm.bind_tools(tools)\n",
    "\n",
    "def chatbot(state: State):\n",
    "    message = llm_with_tools.invoke(state[\"messages\"])\n",
    "    return {\"messages\": [message]}\n",
    "\n",
    "graph_builder.add_node(\"chatbot\", chatbot)\n",
    "\n",
    "tool_node = ToolNode(tools=tools)\n",
    "graph_builder.add_node(\"tools\", tool_node)\n",
    "\n",
    "graph_builder.add_conditional_edges(\"chatbot\", tools_condition)\n",
    "\n",
    "graph_builder.add_edge(\"tools\", \"chatbot\")\n",
    "graph_builder.add_edge(START, \"chatbot\")\n",
    "\n",
    "memory = MemorySaver()\n",
    "graph = graph_builder.compile(checkpointer=memory)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "46c8df3b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "try:\n",
    "    display(Image(graph.get_graph().draw_mermaid_png()))\n",
    "except Exception:\n",
    "    # This requires some extra dependencies and is optional\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "687901dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.tools import tool\n",
    "from langgraph.types import Command, interrupt\n",
    "\n",
    "@tool\n",
    "def human_assistance(query: str) -> str:\n",
    "    \"\"\"Request assistance from a human.\"\"\"\n",
    "    human_response = interrupt({\"query\": query})\n",
    "    return human_response[\"data\"]\n",
    "\n",
    "tools = [search_tool, human_assistance]\n",
    "llm_with_tools = llm.bind_tools(tools)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "9ef5c72d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def chatbot(state: State):\n",
    "    message = llm_with_tools.invoke(state[\"messages\"])\n",
    "    # Because we will be interrupting during tool execution,\n",
    "    # we disable parallel tool calling to avoid repeating any\n",
    "    # tool invocations when we resume.\n",
    "    assert len(message.tool_calls) <= 1\n",
    "    return {\"messages\": [message]}\n",
    "\n",
    "graph_builder = StateGraph(State)\n",
    "\n",
    "graph_builder.add_node(\"chatbot\", chatbot)\n",
    "\n",
    "tool_node = ToolNode(tools=tools)\n",
    "graph_builder.add_node(\"tools\", tool_node)\n",
    "\n",
    "graph_builder.add_conditional_edges(\"chatbot\", tools_condition)\n",
    "\n",
    "graph_builder.add_edge(\"tools\", \"chatbot\")\n",
    "graph_builder.add_edge(START, \"chatbot\")\n",
    "\n",
    "memory = MemorySaver()\n",
    "graph = graph_builder.compile(checkpointer=memory)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0c28ecbe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "try:\n",
    "    display(Image(graph.get_graph().draw_mermaid_png()))\n",
    "except Exception:\n",
    "    # This requires some extra dependencies and is optional\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "13238274",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "\n",
      "我需要一些专家指导来构建智能体。你能帮我申请一下吗？\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Tool Calls:\n",
      "  human_assistance (call_47f8a97b8c2744269ea3a2)\n",
      " Call ID: call_47f8a97b8c2744269ea3a2\n",
      "  Args:\n",
      "    query: 我需要一些专家指导来构建智能体。你能帮我申请一下吗？\n"
     ]
    }
   ],
   "source": [
    "user_input = \"我需要一些专家指导来构建智能体。你能帮我申请一下吗？\"\n",
    "\n",
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "\n",
    "events = graph.stream({\"messages\": [{\"role\": \"user\", \"content\": user_input}]}, config, stream_mode=\"values\")\n",
    "for event in events:\n",
    "    if \"messages\" in event:\n",
    "        event[\"messages\"][-1].pretty_print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "d055e0d5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Tool Calls:\n",
      "  human_assistance (call_47f8a97b8c2744269ea3a2)\n",
      " Call ID: call_47f8a97b8c2744269ea3a2\n",
      "  Args:\n",
      "    query: 我需要一些专家指导来构建智能体。你能帮我申请一下吗？\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: human_assistance\n",
      "\n",
      "我们的PyTorch研习社专家团队随时为您提供帮助！我们建议您使用 LangGraph 来构建您的智能体。它比简单的自主智能体更加可靠，扩展性也更强。\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "很高兴为您提供帮助！LangGraph 是一个非常适合构建智能体的框架，它具有更高的可靠性和扩展性。如果您有任何具体的问题或需要进一步的帮助，请随时告诉我们！\n"
     ]
    }
   ],
   "source": [
    "human_response = (\n",
    "    \"我们的PyTorch研习社专家团队随时为您提供帮助！我们建议您使用 LangGraph 来构建您的智能体。\"\n",
    "    \"它比简单的自主智能体更加可靠，扩展性也更强。\"\n",
    ")\n",
    "\n",
    "human_command = Command(resume={\"data\": human_response})\n",
    "\n",
    "events = graph.stream(human_command, config, stream_mode=\"values\")\n",
    "for event in events:\n",
    "    if \"messages\" in event:\n",
    "        event[\"messages\"][-1].pretty_print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "666901ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "class State(TypedDict):\n",
    "    messages: Annotated[list, add_messages]\n",
    "    name: str\n",
    "    birthday: str"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "80331f5f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.messages import ToolMessage\n",
    "from langchain_core.tools import InjectedToolCallId\n",
    "\n",
    "@tool\n",
    "# Note that because we are generating a ToolMessage for a state update, we\n",
    "# generally require the ID of the corresponding tool call. We can use\n",
    "# LangChain's InjectedToolCallId to signal that this argument should not\n",
    "# be revealed to the model in the tool's schema.\n",
    "def human_assistance(\n",
    "    name: str, birthday: str, tool_call_id: Annotated[str, InjectedToolCallId]\n",
    ") -> str:\n",
    "    \"\"\"Request assistance from a human.\"\"\"\n",
    "    human_response = interrupt(\n",
    "        {\n",
    "            \"question\": \"Is this correct?\",\n",
    "            \"name\": name,\n",
    "            \"birthday\": birthday,\n",
    "        },\n",
    "    )\n",
    "    # If the information is correct, update the state as-is.\n",
    "    if human_response.get(\"correct\", \"\").lower().startswith(\"y\"):\n",
    "        verified_name = name\n",
    "        verified_birthday = birthday\n",
    "        response = \"Correct\"\n",
    "    # Otherwise, receive information from the human reviewer.\n",
    "    else:\n",
    "        verified_name = human_response.get(\"name\", name)\n",
    "        verified_birthday = human_response.get(\"birthday\", birthday)\n",
    "        response = f\"Made a correction: {human_response}\"\n",
    "\n",
    "    # This time we explicitly update the state with a ToolMessage inside\n",
    "    # the tool.\n",
    "    state_update = {\n",
    "        \"name\": verified_name,\n",
    "        \"birthday\": verified_birthday,\n",
    "        \"messages\": [ToolMessage(response, tool_call_id=tool_call_id)],\n",
    "    }\n",
    "    # We return a Command object in the tool to update our state.\n",
    "    return Command(update=state_update)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "20683029",
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [search_tool, human_assistance]\n",
    "llm_with_tools = llm.bind_tools(tools)\n",
    "\n",
    "\n",
    "def chatbot(state: State):\n",
    "    message = llm_with_tools.invoke(state[\"messages\"])\n",
    "    # Because we will be interrupting during tool execution,\n",
    "    # we disable parallel tool calling to avoid repeating any\n",
    "    # tool invocations when we resume.\n",
    "    assert len(message.tool_calls) <= 1\n",
    "    return {\"messages\": [message]}\n",
    "\n",
    "\n",
    "graph_builder = StateGraph(State)\n",
    "\n",
    "graph_builder.add_node(\"chatbot\", chatbot)\n",
    "\n",
    "tool_node = ToolNode(tools=tools)\n",
    "graph_builder.add_node(\"tools\", tool_node)\n",
    "\n",
    "graph_builder.add_conditional_edges(\n",
    "    \"chatbot\",\n",
    "    tools_condition,\n",
    ")\n",
    "graph_builder.add_edge(\"tools\", \"chatbot\")\n",
    "graph_builder.add_edge(START, \"chatbot\")\n",
    "\n",
    "memory = MemorySaver()\n",
    "\n",
    "graph = graph_builder.compile(checkpointer=memory)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "1fd9621c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "try:\n",
    "    display(Image(graph.get_graph().draw_mermaid_png()))\n",
    "except Exception:\n",
    "    # This requires some extra dependencies and is optional\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "68165d37",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "\n",
      "图灵是什么时候出生的？当你准备好答案之后，先使用 human_assistance 工具让专家审核。\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Tool Calls:\n",
      "  human_assistance (call_8eb878f617584301856fa2)\n",
      " Call ID: call_8eb878f617584301856fa2\n",
      "  Args:\n",
      "    name: 艾伦·图灵\n",
      "    birthday: 1912年6月23日\n"
     ]
    }
   ],
   "source": [
    "user_input = (\n",
    "    \"图灵是什么时候出生的？\"\n",
    "    \"当你准备好答案之后，先使用 human_assistance 工具让专家审核。\"\n",
    ")\n",
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "\n",
    "events = graph.stream(\n",
    "    {\"messages\": [{\"role\": \"user\", \"content\": user_input}]},\n",
    "    config,\n",
    "    stream_mode=\"values\",\n",
    ")\n",
    "for event in events:\n",
    "    if \"messages\" in event:\n",
    "        event[\"messages\"][-1].pretty_print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "29779d43",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Tool Calls:\n",
      "  human_assistance (call_8eb878f617584301856fa2)\n",
      " Call ID: call_8eb878f617584301856fa2\n",
      "  Args:\n",
      "    name: 艾伦·图灵\n",
      "    birthday: 1912年6月23日\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: human_assistance\n",
      "\n",
      "Made a correction: {'name': '艾伦·麦席森·图灵', 'birthday': '1912-06-23'}\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "图灵（艾伦·麦席森·图灵）出生于1912年6月23日。\n"
     ]
    }
   ],
   "source": [
    "human_command = Command(\n",
    "    resume={\n",
    "        \"name\": \"艾伦·麦席森·图灵\",\n",
    "        \"birthday\": \"1912-06-23\",\n",
    "    },\n",
    ")\n",
    "\n",
    "events = graph.stream(human_command, config, stream_mode=\"values\")\n",
    "for event in events:\n",
    "    if \"messages\" in event:\n",
    "        event[\"messages\"][-1].pretty_print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "7bb7615b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': '艾伦·麦席森·图灵', 'birthday': '1912-06-23'}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "snapshot = graph.get_state(config)\n",
    "\n",
    "{k: v for k, v in snapshot.values.items() if k in (\"name\", \"birthday\")}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6b210a33",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "StateSnapshot(values={'messages': [HumanMessage(content='图灵是什么时候出生的？当你准备好答案之后，先使用 human_assistance 工具让专家审核。', additional_kwargs={}, response_metadata={}, id='203701ee-972f-41cf-9370-bf0b38eb5949'), AIMessage(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_8eb878f617584301856fa2', 'function': {'arguments': '{\"name\": \"艾伦·图灵\", \"birthday\": \"1912年6月23日\"}', 'name': 'human_assistance'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'qwen3-32b'}, id='run--be078b73-8cfe-488a-84f3-f467ca3dbd87-0', tool_calls=[{'name': 'human_assistance', 'args': {'name': '艾伦·图灵', 'birthday': '1912年6月23日'}, 'id': 'call_8eb878f617584301856fa2', 'type': 'tool_call'}]), ToolMessage(content=\"Made a correction: {'name': '艾伦·麦席森·图灵', 'birthday': '1912-06-23'}\", name='human_assistance', id='eecb3f09-f3a2-414a-9ed3-4f62fd7bd5cd', tool_call_id='call_8eb878f617584301856fa2'), AIMessage(content='图灵（艾伦·麦席森·图灵）出生于1912年6月23日。', additional_kwargs={}, response_metadata={'finish_reason': 'stop', 'model_name': 'qwen3-32b'}, id='run--7ed9dd2f-3e18-4017-9357-5d75bde505a8-0')], 'name': '艾伦·麦席森·图灵', 'birthday': '1912-06-23'}, next=(), config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1f079815-1cc9-67fb-8003-20fa71927021'}}, metadata={'source': 'loop', 'writes': {'chatbot': {'messages': [AIMessage(content='图灵（艾伦·麦席森·图灵）出生于1912年6月23日。', additional_kwargs={}, response_metadata={'finish_reason': 'stop', 'model_name': 'qwen3-32b'}, id='run--7ed9dd2f-3e18-4017-9357-5d75bde505a8-0')]}}, 'thread_id': '1', 'step': 3, 'parents': {}}, created_at='2025-08-15T02:41:17.858811+00:00', parent_config={'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1f079815-1180-616b-8002-8e534e83ad6a'}}, tasks=())"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "snapshot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "2015d209",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Num Messages:  4 Next:  ()\n",
      "--------------------------------------------------------------------------------\n",
      "Num Messages:  3 Next:  ('chatbot',)\n",
      "--------------------------------------------------------------------------------\n",
      "Num Messages:  2 Next:  ('tools',)\n",
      "--------------------------------------------------------------------------------\n",
      "Num Messages:  1 Next:  ('chatbot',)\n",
      "--------------------------------------------------------------------------------\n",
      "Num Messages:  0 Next:  ('__start__',)\n",
      "--------------------------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "to_replay = None\n",
    "for state in graph.get_state_history(config):\n",
    "    print(\"Num Messages: \", len(state.values[\"messages\"]), \"Next: \", state.next)\n",
    "    print(\"-\" * 80)\n",
    "    if len(state.values[\"messages\"]) == 2:\n",
    "        # We are somewhat arbitrarily selecting a specific state based on the number of chat messages in the state.\n",
    "        to_replay = state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "e89db546",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('tools',)\n",
      "{'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1f079814-cbcf-6b58-8001-c21faad329a8'}}\n"
     ]
    }
   ],
   "source": [
    "print(to_replay.next)\n",
    "print(to_replay.config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "90978db1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Tool Calls:\n",
      "  human_assistance (call_8eb878f617584301856fa2)\n",
      " Call ID: call_8eb878f617584301856fa2\n",
      "  Args:\n",
      "    name: 艾伦·图灵\n",
      "    birthday: 1912年6月23日\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: human_assistance\n",
      "\n",
      "Made a correction: {'name': '艾伦·麦席森·图灵', 'birthday': '1912-06-23'}\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "图灵（艾伦·麦席森·图灵）出生于1912年6月23日。\n"
     ]
    }
   ],
   "source": [
    "# The `checkpoint_id` in the `to_replay.config` corresponds to a state we've persisted to our checkpointer.\n",
    "for event in graph.stream(None, to_replay.config, stream_mode=\"values\"):\n",
    "    if \"messages\" in event:\n",
    "        event[\"messages\"][-1].pretty_print()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
